/**
@author		Jong Min, Lee
@date		  01/23/2014
@brief		tool data administrator

copyright(c) Tae Young Soft. All right reserved. 2014
*/
#pragma once

#include <vector>
#include <map>
#include "Taurus_Util/Macros.h"
#include "Taurus_ToolData/TTDefine.h"
#include "Taurus_ToolData/ToolData.h"
#include "Taurus_ToolData/ToolboxData.h"

/**
@brief tool data administrator
*/
class TAURUS_TOOLDATA_EXPORT CToolDataAdmin
{
public:
  enum
  {
    NormalToolButtonWidth   = 36,   //tool button width for normal resolution monitor
    NormalToolButtonHeight  = 36,   //tool button height for normal resolution monitor

    HighToolButtonWidth     = 60,   //tool button width for high resolution monitor
    HighToolButtonHeight    = 60    //tool button height for high resolution monitor
  };

private:
  DISALLOW_COPY_AND_ASSIGN(CToolDataAdmin);

  /**
  @brief		default constructor
  */
  CToolDataAdmin();

public:

  /**
  @brief		destructor
  */
  ~CToolDataAdmin();

  /**
  @brief		get pointer to the single instance of  tool data administrator
  @return		pointer to the single instance of tool data administrator
  */
  static CToolDataAdmin* getInstance();

  /**
  @brief		load tool data
  @param		bLoad2K flag indicating whether this load button bitmap for high resolution monitor
  @return		ERROR_SUCCESS if succeeds, an error code if not
  */
  DWORD loadData(BOOL bLoad2K);

  /**
  @brief		search a tool data by command ID
  @param		uCmdID command ID
  @return		pointer to tool data if this method finds the tool data, NULL if not
  */
  const CToolData* search_CmdID(UINT uCmdID) const;

  /**
  @brief		search a tool data by tool data ID
  @param		uID tool data ID
  @return		pointer to tool data if this method finds the tool data, NULL if not
  */
  const CToolData* search_ID(UINT uID) const;

  /**
  @brief		applies function fn to each of tool data belong to specified group
  @param		pszGroupName pointer to group name string
  @param    fn unary function that accepts pointer to const tool data as parameter
            if fn return false, this method sop applying fn
  */
  template<class Function>
  void forEachToolData(const TCHAR* pszGroupName, Function fn) const;

  /**
  @brief		get the number of tool data belong to specified group
  @param		pszGruopName pointer to group name string
  @return		the number of tool data
  */
  unsigned getNumToolData(const TCHAR* pszGroupName) const;

  /**
  @brief		get group name by using index number
  @param		nIndex the index number of group
  @return		pointer to group name string if found, NULL if not
  */
  const TCHAR* getGroupName(unsigned nIndex) const;

  /**
  @brief		create the default toolbox data
  @param		cContainer container to be store the default toolbox data
  @return		ERROR_SUCCESS if succeeds, an error code if not
  */
  DWORD createDefaultToolboxData(std::list<CToolboxData*>& cContainer) const;

private:
  /**
  @brief		create common tool data
  @return		ERROR_SUCCESS if succeeds, an error code if not
  */
  DWORD createCommonToolData(BOOL bLoad2K);

  /**
  @brief		create annotation tool data
  @return		ERROR_SUCCESS if succeeds, an error code if not
  */
  DWORD createAnnotationToolData(BOOL bLoad2K);

  /**
  @brief		create od tool data
  @return		ERROR_SUCCESS if succeeds, an error code if not
  */
  DWORD createODToolData(BOOL bLoad2K);

  /**
  @brief		create etc tool data
  @return		ERROR_SUCCESS if succeeds, an error code if not
  */
  DWORD createETCToolData(BOOL bLoad2K);

  /**
  @brief		destroy all tool data
  */
  void destroyToolData();

  /**
  @brief		create default toolbox data
  @param		pszGroupName pointer to group name
  @param    pOutToolbox variable in which pointer to default toolbox data is stored
  @return   ERROR_SUCCESS if succeeds, an error code if not
  */
  DWORD createDefaultToolboxData(const TCHAR* pszGroupName,
                                 CToolboxData*& pOutToolboxData) const;

private:
  //pointer to the single instance of this class
  static CToolDataAdmin* m_pInstance;

  //tool data
  std::map<CString, std::vector<CToolData*>*> m_mapToolGroups;
};

template<class Function>
void CToolDataAdmin::forEachToolData(const TCHAR* pszGroupName, Function fn) const
{
  if(pszGroupName == NULL)
    return;

  //find tool data group
  auto gpos = m_mapToolGroups.find[pszGroupName];
  if(gpos = m_mapToolGroups.end())
    return;

  //apply fn each of tool data
  std::vector<CToolData*>* pToolData = (*(gpos.second));
  auto first = pToolData->cbegin();
  auto last = pToolData->cend();
  while (first != last)
  {
    if(fn(static_cast<const CToolData*>(*first))) break;
    ++first;
  }
}